package com.hexun.es.dao;

import com.alibaba.fastjson.JSONObject;
import com.hexun.es.model.Person;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexResponse;
import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsRequest;
import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsResponse;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequestBuilder;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;

import java.util.*;

/**
 * @description:
 * @author:yrw
 * @date 2018/11/20
 */
@Component
public class EsDao {

    private static final Logger logger = LoggerFactory.getLogger(EsDao.class);

    @Autowired
    private TransportClient client;

    /**
     * 创建索引
     *
     * @param index
     * @return
     */
    public boolean createIndex(String index) {
        if (!isIndexExist(index)) {
            logger.info("Index is not exits!");
        }
        CreateIndexResponse buildIndexresponse = client.admin().indices().prepareCreate(index).execute().actionGet();
        logger.info(" 创建索引的标志: " + buildIndexresponse.isAcknowledged());
        return buildIndexresponse.isAcknowledged();
    }

    /**
     * 删除索引
     *
     * @param index
     * @return
     */
    public boolean deleteIndex(String index) {
        if (!isIndexExist(index)) {
            logger.info(" 索引不存在 ！！！！！!");
        }
        DeleteIndexResponse diResponse = client.admin().indices().prepareDelete(index).execute().actionGet();
        if (diResponse.isAcknowledged()) {
            logger.info("删除索引**成功** index->>>>>>>" + index);
        } else {
            logger.info("删除索引**失败** index->>>>> " + index);
        }
        return diResponse.isAcknowledged();
    }

    /**
     * 查询数据
     *
     * @param index 索引<----->关系型数据库
     * @param type  类型<----->关系型数据表
     * @param id    数据ID<----->id
     * @return
     */
    public Map<String, Object> searchById(String index, String type, String id) {
        if (index == null || type == null || id == null) {
            logger.info(" 无法查询数据，缺唯一值!!!!!!! ");
            return null;
        }
        //来获取查询数据信息
        GetRequestBuilder getRequestBuilder = client.prepareGet(index, type, id);
        GetResponse getResponse = getRequestBuilder.execute().actionGet();
        //这里也有指定的时间获取返回值的信息，如有特殊需求可以
        return getResponse.getSource();
    }

    /**
     * 更新数据
     *
     * @param data  添加的数据类型 json格式的
     * @param index 索引<----->关系型数据库
     * @param type  类型<----->关系型数据表
     * @param id    数据ID<----->id
     * @return
     */
    public void updateById(JSONObject data, String index, String type, String id) {
        if (index == null || type == null || id == null) {
            logger.info(" 无法更新数据，缺唯一值!!!!!!! ");
            return;
        }

        //更新步骤
        UpdateRequest up = new UpdateRequest();
        up.index(index).type(type).id(id).doc(data);

        //获取响应信息
        //.actionGet(timeoutMillis)，也可以用这个方法，当过了一定的时间还没得到返回值的时候，就自动返回。
        UpdateResponse response = client.update(up).actionGet();
        logger.info("更新数据状态信息，status{}", response.status().getStatus());
    }

    /**
     * 添加数据
     *
     * @param data  添加的数据类型 json格式
     * @param index 索引<----->关系型数据库
     * @param type  类型<----->关系型数据表
     * @param id    数据ID<----->id
     * @return
     */
    public String addData(JSONObject data, String index, String type, String id) {
        //判断一下id是否为空，为空的话就设置一个id
        if (id == null) {
            id = UUID.randomUUID().toString();
        }
        //添加数据
        IndexResponse response = client.prepareIndex(index, type, id).setSource(data).get();
        logger.info("add 添加数据的状态:{}", response.status().getStatus());
        return response.getId();
    }

    /**
     * 通过ID删除数据
     *
     * @param index 索引，类似数据库
     * @param type  类型，类似表
     * @param id    数据ID
     */
    public void deleteById(String index, String type, String id) {
        if (index == null || type == null || id == null) {
            logger.info(" 无法删除数据，缺唯一值!!!!!!! ");
            return;
        }
        //开始删除数据
        DeleteResponse response = client.prepareDelete(index, type, id).execute().actionGet();
        logger.info("删除数据状态，status-->>>>{},", response.status().getStatus());
    }

    /**
     * 判断索引是否存在
     *
     * @param index
     * @return
     */
    public boolean isIndexExist(String index) {
        IndicesExistsResponse iep = client.admin().indices().exists(new IndicesExistsRequest(index)).actionGet();
        if (iep.isExists()) {
            logger.info("此索引 [" + index + "] 已经在ES集群里存在");
        } else {
            logger.info(" 没有此索引 [" + index + "] ");
        }
        return iep.isExists();
    }

    /**
     * 查询
     * @param pageNo 当前页
     * @param pageSize 一页多少记录
     * @param fieldSort 排序字段
     * @param sortOrder 升序还是降序
     * @param p
     * @return
     */
    public  List<Map<String,Object>> searchPerson(Integer pageNo, Integer pageSize, String fieldSort, String sortOrder, Person p) {
        //构建查询条件
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        if (p.getId() != null) {
            boolQueryBuilder.must(QueryBuilders.matchQuery("id", p.getId()));
        }
        if (StringUtils.isNotBlank(p.getName())) {
            boolQueryBuilder.must(QueryBuilders.matchQuery("name", p.getName()));
        }
        if (p.getAge() != null) {
            boolQueryBuilder.must(QueryBuilders.matchQuery("age", p.getAge()));
        }
        if (StringUtils.isNotBlank(p.getAddress())) {
            boolQueryBuilder.must(QueryBuilders.matchQuery("address", p.getAddress()));
        }

        //如果pageNo为空，默认赋值
        if(pageNo == null){
            pageNo=1;
        }
        //如果pageNo为空，默认赋值
        if(pageSize == null){
            pageSize=10;
        }

        //排序
        FieldSortBuilder fieldSortBuilder = null;
        if(StringUtils.isNotBlank(fieldSort)&&StringUtils.isNotBlank(sortOrder)){
            if(sortOrder.equals("desc")){
                fieldSortBuilder= SortBuilders.fieldSort(fieldSort).order(SortOrder.DESC);
            }else {
                fieldSortBuilder = SortBuilders.fieldSort(fieldSort).order(SortOrder.ASC);
            }
        }


        SearchRequestBuilder searchRequestBuilder;
        if(fieldSortBuilder == null){
            searchRequestBuilder = client.prepareSearch("yurenwei-test")
                    .setTypes("person")
                    .setQuery(boolQueryBuilder)
                    .setFrom(pageNo-1)
                    .setSize(pageSize);
        }else{
            searchRequestBuilder = client.prepareSearch("yurenwei-test")
                    .setTypes("person")
                    .setQuery(boolQueryBuilder)
                    .setFrom(pageNo-1)
                    .setSize(pageSize)
                    .addSort(fieldSortBuilder);
        }

        SearchResponse response = searchRequestBuilder.get();
        List<Map<String,Object>> mapList=new ArrayList<Map<String, Object>>();
        for (SearchHit hit : response.getHits()) {
            mapList.add(hit.getSource());
        }
        return mapList;
    }

}